package persistencia.daos;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Properties;

import persistencia.consultas.Consultas;
import logica.Avion;
import logica.Blindado;
import logica.Drone;
import logica.Jugador;
import logica.Personaje;
import logica.Personajes;
import logica.Piloto;

public class DAOPersonajes {

	public DAOPersonajes() {
		
	}
		
	/**
	 * Obtiene el personaje correspondiente al id ingresado por parametro
	 * @param idObjeto
	 * @return
	 * @throws Exception
	 */
	public Personaje find(int idObjeto) throws Exception{
		Personaje per = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		Connection conn = null;
		Consultas consultas = new Consultas();
		Properties p = new Properties();
		Properties p2 = new Properties();
				
		try {
			p.load(new FileInputStream("project.properties"));
			p2.load(new FileInputStream("properties.properties"));
			int vision = Integer.parseInt(p2.getProperty("Piloto.vision"));
			int velocidad = Integer.parseInt(p2.getProperty("Piloto.velocidad"));
			conn = DriverManager.getConnection(p.getProperty("url"), p.getProperty("usr"),
					p.getProperty("pass"));
			ps = conn.prepareStatement(consultas.obtenerPersonaje());
			ps.setInt(1, idObjeto);
			
			rs = ps.executeQuery();
			
			if(rs.next()){
				if(rs.getInt("tipoObjeto") == 1){//es personaje
					switch (rs.getInt("tipoPersonaje")){
					case 1:per = new Piloto(0, rs.getFloat("coordenadaX"), rs.getFloat("coordenadaY"), rs.getFloat("alturaObjeto"), 
							rs.getFloat("anchoObjeto"), rs.getInt("vidaActual"), vision, velocidad);
							break;
					case 2:per = new Avion(1, rs.getFloat("coordenadaX"), rs.getFloat("coordenadaY"), rs.getFloat("alturaObjeto"), 
							rs.getFloat("anchoObjeto"), rs.getInt("vidaActual"), vision*6, velocidad*6, rs.getInt("municionArtilleria"), 
							vision*6, Integer.valueOf(p2.getProperty("Avion.danioArtilleria")), Boolean.valueOf(p2.getProperty("Avion.artilleriaInfinita")),
							rs.getInt("municionBombas"), Integer.parseInt(p2.getProperty("Avion.danioArtilleria")));
							break;
					case 3:per = new Drone(2, rs.getFloat("coordenadaX"), rs.getFloat("coordenadaY"), rs.getFloat("alturaObjeto"), 
							rs.getFloat("anchoObjeto"), rs.getInt("vidaActual"), vision, velocidad*2, false, false, "6");
							break;
					case 4:per = new Blindado(0, rs.getFloat("coordenadaX"), rs.getFloat("coordenadaY"), rs.getFloat("alturaObjeto"), 
							rs.getFloat("anchoObjeto"), rs.getInt("vidaActual"), vision*3, velocidad*2, rs.getInt("municionArtilleria"), 
							vision*2, Integer.parseInt(p2.getProperty("Blindado2.danioArtilleria")), 
							Boolean.parseBoolean(p2.getProperty("Blindado2.artilleriaInfinita")));
							break;
					case 5:per = new Blindado(1, rs.getFloat("coordenadaX"), rs.getFloat("coordenadaY"), rs.getFloat("alturaObjeto"), 
							rs.getFloat("anchoObjeto"), rs.getInt("vidaActual"), vision*3, velocidad*2, rs.getInt("municionArtilleria"), 
							vision*2, Integer.parseInt(p2.getProperty("Blindado2.danioArtilleria")), 
							Boolean.parseBoolean(p2.getProperty("Blindado2.artilleriaInfinita")));
							break;
					default: throw new Exception("Tipo de personaje no valido");
					}
					
				}
				else{
					throw new Exception("El objeto no es un personaje");
				}
				
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
			throw new Exception(e);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new Exception(e);
		} catch (IOException e) {
			e.printStackTrace();
			throw new Exception(e);
		} finally{
			if(conn != null){conn.close();}
			if(rs != null){rs.close();}
			if(ps != null){ps.close();}
		}

		return per;
	}
	
	/**
	 * Obtiene los personajes correspondientes a una partida
	 * @param idPartida
	 * @return
	 * @throws Exception
	 */
	public Personajes findAccPart(int idPartida) throws Exception{
		Personajes pers = new Personajes(5);
		PreparedStatement ps = null;
		ResultSet rs = null;
		ResultSet rs2 = null;
		Connection conn = null;
		Consultas consultas = new Consultas();
		Properties p = new Properties();
		int i = 0;
		
		try {
			p.load(new FileInputStream("project.properties"));
			conn = DriverManager.getConnection(p.getProperty("url"), p.getProperty("usr"), p.getProperty("pass"));
			ps = conn.prepareStatement(consultas.obtenerObjetosEscenarioPartida());
			ps.setInt(1, idPartida);
			rs = ps.executeQuery();
			
			while(rs.next()){
				ps = conn.prepareStatement(consultas.obtenerTipoObjeto());
				ps.setInt(1, rs.getInt("idObjeto"));
				rs2 = ps.executeQuery();

				if(rs2.next()){
					if(rs2.getInt("tipoObjeto") == 1){//es un personaje{
						pers.getArray()[i] = this.find(rs.getInt("idObjeto"));
						i++;				
					}
				}
				
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new Exception(e);
		} catch (IOException e) {
			e.printStackTrace();
			throw new Exception(e);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new Exception(e);
		} finally{
			if(conn != null){conn.close();}
			if(ps != null){ps.close();}
			if(rs != null){rs.close();}
		}
	
		return pers;
	}
	
	/**
	 * Obtiene los ids de los personajes actuales de una partida (con los que estaba jugando
	 * el participante al momento de guardarla)
	 * @param idPartida
	 * @return
	 * @throws Exception
	 */
	
	public ArrayList<Integer> obtenerIdsActualesPersonajes(int idPartida) throws Exception{
		ArrayList<Integer> arr_ids = new ArrayList<>();
		PreparedStatement ps = null;
		ResultSet rs = null;
		Connection conn = null;
		Consultas consultas = new Consultas();
		Properties p = new Properties();
		
		try {
			p.load(new FileInputStream("project.properties"));
			conn = DriverManager.getConnection(p.getProperty("url"), p.getProperty("usr"), p.getProperty("pass"));
			ps = conn.prepareStatement(consultas.obtenerPersonajesActuales());
			ps.setInt(1, idPartida);
			rs = ps.executeQuery();
			
			while(rs.next()){
				int tipo = rs.getInt("tipoPersonaje");
				if(tipo ==1 || tipo ==4)
					arr_ids.add(0);
				else if(tipo ==2 || tipo ==5)
					arr_ids.add(1);			
			}
		} catch (SQLException e) {
			e.printStackTrace();
			throw new Exception(e);
		} finally{
			if(conn != null){conn.close();}
			if(rs != null){rs.close();}
			if(ps != null){ps.close();}
		}
		
		return arr_ids;
	}
	
	public ArrayList<Integer> obtenerIdsPersonajesPartida(int idPartida) throws Exception{
		ArrayList<Integer> arr_ids = new ArrayList<>();
		PreparedStatement ps = null;
		ResultSet rs = null;
		Connection conn = null;
		Consultas consultas = new Consultas();
		Properties p = new Properties();
		
		try {
			p.load(new FileInputStream("project.properties"));
			conn = DriverManager.getConnection(p.getProperty("url"), p.getProperty("usr"), p.getProperty("pass"));
			ps = conn.prepareStatement(consultas.obtenerIdsPersonajesPartida());
			ps.setInt(1, idPartida);
			rs = ps.executeQuery();
			
			while(rs.next())
				arr_ids.add(rs.getInt("idObjeto"));
	
		} catch (SQLException e) {
			e.printStackTrace();
			throw new Exception(e);
		} finally{
			if(conn != null){conn.close();}
			if(rs != null){rs.close();}
			if(ps != null){ps.close();}
		}
		
		return arr_ids;
	}

	/**
	 * Inserta en la base los personajes de un jugador y carga la tabla objetos_actuales
	 * con los dis de los objetos ingresados y el id de la partida correspondiente
	 * @param j
	 * @param idPartida
	 * @throws Exception
	 */
	public void insert(Jugador j, int idPartida) throws Exception{
		PreparedStatement ps = null;
		ResultSet rs = null;
		Connection conn = null;
		Consultas consultas = new Consultas();
		Properties p = new Properties();
		int ultimoId = 0;
		
		try {
			p.load(new FileInputStream("project.properties"));
			conn = DriverManager.getConnection(p.getProperty("url"), p.getProperty("usr"), p.getProperty("pass"));
			for(int i=0 ; i<j.getPersonajes().getArray().length ; i++){
				//se hace el insert en la tabla objetos
				ps = conn.prepareStatement(consultas.insertObjetos());
				ps.setNull(1, java.sql.Types.DECIMAL);
				ps.setInt(2, 1);
				ps.setFloat(3, j.getPersonajes().getArray()[i].getCoordenadaX());
				ps.setFloat(4, j.getPersonajes().getArray()[i].getCoordenadaY());
				ps.setFloat(5, j.getPersonajes().getArray()[i].getAlturaObjeto());
				ps.setFloat(6, j.getPersonajes().getArray()[i].getAnchoObjeto());
				
				ps.executeUpdate();
				
				//se hace el insert en la tabla objetos_actuales
				ps = conn.prepareStatement(consultas.obtenerUltimoIndiceObjetos());
				rs = ps.executeQuery();
				
				if(rs.next())
					ultimoId = rs.getInt("ultimoId");
				
				ps = conn.prepareStatement(consultas.insertObjetosActuales());
				ps.setInt(1, idPartida);
				ps.setInt(2, ultimoId);
				ps.executeUpdate();
				
				//Se hace el insert en la tabla personajes
				ps = conn.prepareStatement(consultas.insertPersonajes());
				ps.setInt(1, ultimoId);
				
				if(j.getPersonajes().getArray()[i] instanceof Piloto)
					ps.setInt(2, 1);
				else{
					if(j.getPersonajes().getArray()[i] instanceof Avion)
						ps.setInt(2, 2);
					else{
						if(j.getPersonajes().getArray()[i] instanceof Drone)
							ps.setInt(2, 3);
						else{
							if(j.getPersonajes().getArray()[i] instanceof Blindado){
								if(i == 0)
									ps.setInt(2, 4);
								else
									ps.setInt(2, 5);
							}
							
						}
					}
				}
				
				if(j.getPersonajes().getArray()[i] instanceof Avion)
					ps.setInt(3, ((Avion)j.getPersonajes().getArray()[i]).getMunicionBomba());
				else
					ps.setInt(3, 0);
				
				ps.setInt(4, j.getPersonajes().getArray()[i].getVida());
				if(j.getPersonajes().getArray()[i] instanceof Avion)
					ps.setInt(5, ((Avion)j.getPersonajes().getArray()[i]).getMunicionArtilleria());
				else{
					if(j.getPersonajes().getArray()[i] instanceof Blindado){
						ps.setInt(5, ((Blindado)j.getPersonajes().getArray()[i]).getMunicionArtilleria());
					}
					else{
						ps.setInt(5, 0);
					}
				}
				
				if(j.getIdPersonajeActual() == i)
					ps.setInt(6, 1);
				else
					ps.setInt(6, 0);
				
				ps.executeUpdate();
					
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new Exception(e);
		} catch (IOException e) {
			e.printStackTrace();
			throw new Exception(e);
		} catch (SQLException e) {
			e.printStackTrace();
			throw new Exception(e);
		} finally{
			if(conn != null){conn.close();}
			if(rs != null){rs.close();}
			if(ps != null){ps.close();}
		}
		
	}
	
	public void delete(int idPersonaje) throws Exception{
		PreparedStatement ps = null;
		ResultSet rs = null;
		Connection conn = null;
		Consultas consultas = new Consultas();
		Properties p = new Properties();
		
		try {
			p.load(new FileInputStream("project.properties"));
			conn = DriverManager.getConnection(p.getProperty("url"), p.getProperty("usr"), p.getProperty("pass"));
			ps = conn.prepareStatement(consultas.deletePersonaje());
			ps.setInt(1, idPersonaje);
			ps.executeUpdate();
			
			ps = conn.prepareStatement(consultas.deleteObjeto());
			ps.setInt(1, idPersonaje);
			ps.executeUpdate();
			
		} catch (SQLException e) {
			e.printStackTrace();
			throw new Exception(e);
		} finally{
			if(conn != null){conn.close();}
			if(rs != null){rs.close();}
			if(ps != null){ps.close();}
		}
		

	}

}
